package com.springBoot.springBootSysCore.modules.services.system.impl;

import com.springBoot.springBootSysCore.common.config.Global;
import com.springBoot.springBootSysCore.common.service.IBaseServiceImpl;
import com.springBoot.springBootSysCore.common.utils.CacheUtils;
import com.springBoot.springBootSysCore.common.utils.IdGen;
import com.springBoot.springBootSysCore.common.utils.SessionUtils;
import com.springBoot.springBootSysCore.common.utils.returnUtil.CodeEnum;
import com.springBoot.springBootSysCore.common.utils.returnUtil.ResultJsonFormat;
import com.springBoot.springBootSysCore.modules.entity.system.SysCode;
import com.springBoot.springBootSysCore.modules.entity.system.SysResource;
import com.springBoot.springBootSysCore.modules.entity.system.SysRole;
import com.springBoot.springBootSysCore.modules.enums.base.DeleteStateEnum;
import com.springBoot.springBootSysCore.modules.repository.system.SysResourceRepository;
import com.springBoot.springBootSysCore.modules.repository.system.SysRoleRepository;
import com.springBoot.springBootSysCore.modules.repository.system.SysUserRepository;
import com.springBoot.springBootSysCore.modules.services.system.SysResourceService;
import com.springBoot.springBootSysCore.modules.shiro.ShiroFilerChainManager;
import com.springBoot.springBootSysCore.modules.vo.TreeNodeVo;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by timo on 2017/11/7.
 */
@Service
public class SysResourceServiceImpl extends IBaseServiceImpl<SysResource, String> implements SysResourceService {
    @Autowired
    private SysResourceRepository sysResourceRepository;
    @Autowired
    private SysRoleRepository sysRoleRepository;
    @Autowired
    private SysUserRepository sysUserRepository;

    @Autowired
    @SuppressWarnings("SpringJavaAutowiringInspection")
    public JdbcTemplate jdbcTemplate;

    @Autowired
    private ShiroFilerChainManager shiroFilerChainManager;


    @Override
    public List<TreeNodeVo> findTreeRes(String roleId) {
        List<TreeNodeVo> r_list = new ArrayList<TreeNodeVo>();
        List<SysResource> f_list = sysResourceRepository.findAllOfParent();
        List<String> roleResourceId = sysResourceRepository.findResourceForRole(roleId);
        for (SysResource resource : f_list) {
            if(resource.getDelFlag().equals(DeleteStateEnum.YES_DELETE.getVal())){
                continue;
            }
            TreeNodeVo vo = new TreeNodeVo();
            vo.setId(resource.getId());
            vo.setText(resource.getName());
            vo.setName(resource.getName());
            if(roleResourceId.contains(resource.getId())){
                vo.setChecked(true);
            }
            if(!resource.getChildrenResource().isEmpty()){
                vo.setChildren(getChildrenResoucesForzTree(resource,roleResourceId));
            }
            r_list.add(vo);
        }
        return r_list;
    }
    /**
     * [获取角色资源方法的]添加资源zTree树的子节点
     * @param f_resource
     * @param roleResourceId
     * @return
     */
    private List<TreeNodeVo> getChildrenResoucesForzTree(SysResource f_resource, List<String> roleResourceId) {
        List<TreeNodeVo> list = new ArrayList<TreeNodeVo>();
        for (SysResource resource : f_resource.getChildrenResource()) {
            TreeNodeVo vo = new TreeNodeVo();
            vo.setId(resource.getId());
            vo.setText(resource.getName());
            vo.setName(resource.getName());
            if(roleResourceId.contains(resource.getId())){
                vo.setChecked(true);
            }
            if(!resource.getChildrenResource().isEmpty()){
                vo.setChildren(getChildrenResoucesForzTree(resource,roleResourceId));
            }
            list.add(vo);
        }
        return list;
    }
    @Override
    public List<TreeNodeVo> findTreeResOfRes(String resourceId) {
        List<SysResource> f_list;
        Object object= CacheUtils.get("findAllOfParent");

        if(object!=null){
            f_list =(List<SysResource>)object;
        }else{
            f_list = sysResourceRepository.findAllOfParent();
            CacheUtils.put("findAllOfParent",f_list);
        }
        List<TreeNodeVo> treeNodeLi = new ArrayList<TreeNodeVo>();
        for(SysResource resoure : f_list){
            TreeNodeVo vo = new TreeNodeVo();
            vo.setId(resoure.getId());
            vo.setName(resoure.getName());
            vo.setText(resoure.getName());
            vo.setUrl(resoure.getUrl()); //会造成ztree点击跳转
            vo.setIconCls(resoure.getIconClass());
            vo.setIsButton(resoure.getIsButton());
            vo.setCode(resoure.getCode());

            if(resoure.getId().equals(resourceId)){
                continue;
            }
            if(resoure.getChildrenResource()!=null && !resoure.getChildrenResource().isEmpty()){
                vo.setChildren(this.findTreeSonRes(resoure, resourceId));
            }
            treeNodeLi.add(vo);
        }

        return treeNodeLi;
    }


    /**
     * [获取所有资源方法的]添加资源zTree树的子节点
     * @param f_resoure
     * @param resourceId
     * @return
     */
    private List<TreeNodeVo> findTreeSonRes(SysResource f_resoure,String resourceId) {
        List<TreeNodeVo> list = new ArrayList<TreeNodeVo>();
        for(SysResource resoure : f_resoure.getChildrenResource()){
            TreeNodeVo vo = new TreeNodeVo();
            vo.setId(resoure.getId());
            vo.setName(resoure.getName());
            vo.setText(resoure.getName());
            vo.setIsButton(resoure.getIsButton());
            vo.setCode(resoure.getCode());
            vo.setUrl(resoure.getUrl());
            vo.setIconCls(resoure.getIconClass());

            if(resoure.getId().equals(resourceId)){
                continue;
            }
            if(resoure.getChildrenResource()!=null && !resoure.getChildrenResource().isEmpty()){
                vo.setChildren(this.findTreeSonRes(resoure, resourceId));
            }
            list.add(vo);
        }
        return list;
    }


    @Override
    public Object ztreeDataNoUrl(String extId) {
        List<SysResource> f_list;
        Object object= CacheUtils.get("findAllOfParent");
        if(object!=null){
            f_list =(List<SysResource>)object;
        }else{
            f_list = sysResourceRepository.findAllOfParent();
            CacheUtils.put("findAllOfParent",f_list);
        }
        List<Map> mapList = new ArrayList<Map>();
        for(SysResource resoure : f_list){
            Map m = new HashedMap();
            m.put("id",resoure.getId());
            m.put("name",resoure.getName());
            m.put("text",resoure.getName());
            if(resoure.getId().equals(extId)){
                continue;
            }
            if(resoure.getChildrenResource()!=null && !resoure.getChildrenResource().isEmpty()){
                m.put("children",this.findzTreeSonRes(resoure, extId));
            }
            mapList.add(m);
        }
        return mapList;
    }

    private List<Map> findzTreeSonRes(SysResource f_resoure,String resourceId) {
        List<Map> list = new ArrayList<Map>();
        for(SysResource resoure : f_resoure.getChildrenResource()){
            Map m = new HashedMap();
            m.put("id",resoure.getId());
            m.put("name",resoure.getName());
            m.put("text",resoure.getName());
            if(resoure.getId().equals(resourceId)){
                continue;
            }
            if(resoure.getChildrenResource()!=null && !resoure.getChildrenResource().isEmpty()){
                m.put("children",this.findzTreeSonRes(resoure, resourceId));
            }
            list.add(m);
        }
        return list;
    }

    @Override
    public Object layuiMenu() {
        List<SysResource> f_list;
        Object object= CacheUtils.get("findAllOfParent");
        if(object!=null){
            f_list =(List<SysResource>)object;
        }else{
            f_list = sysResourceRepository.findAllOfParent();
            CacheUtils.put("findAllOfParent",f_list);
        }
        List<Map> mapList = new ArrayList<Map>();
        for(SysResource resoure : f_list){
            Map m = new HashedMap();
            m.put("title",resoure.getName());
            m.put("icon",resoure.getIconClass());
            m.put("href", Global.getConfig("server.contextPath")+Global.getAdminPath()+resoure.getUrl());
//            m.put("spread",resoure.getId().equals(""));
            m.put("children",resoure.getName());
            if(resoure.getChildrenResource()!=null && !resoure.getChildrenResource().isEmpty()){
                m.put("children",this.layuiMenuSonRes(resoure));
            }
            if(mapList.size()<1){
                m.put("spread",true);
            }
            mapList.add(m);
        }
        return mapList;
    }
    private List<Map> layuiMenuSonRes(SysResource f_resoure) {
        List<Map> list = new ArrayList<Map>();
        for(SysResource resoure : f_resoure.getChildrenResource()){
            Map m = new HashedMap();
            m.put("title",resoure.getName());
            m.put("icon",resoure.getIconClass());
            m.put("href",Global.getConfig("server.contextPath")+Global.getAdminPath()+resoure.getUrl());
//            m.put("spread",resoure.getId().equals(""));
            m.put("children",resoure.getName());
            if(resoure.getChildrenResource()!=null && !resoure.getChildrenResource().isEmpty()){
                m.put("children",this.layuiMenuSonRes(resoure));
            }
            list.add(m);
        }
        return list;
    }
    @Override
    @Transactional
    public Map<String, Object> deleteResource(List<String> asList) {
        ResultJsonFormat ret = new ResultJsonFormat("删除成功", CodeEnum.SUCCESS.value());
        try {
            List<SysResource> list = sysResourceRepository.findByParentResources(asList);
            if(list.size()>0){
                ret.setMsg("选中的菜单有子级菜单！请先取消关联。");
                ret.setFlag(CodeEnum.ERROR.value());
                return ret.convertResultJson();
            }
//            List<SysRole> roles = sysRoleRepository.findByResourceIds(asList);
//            if(roles.size()>0){
//                ret.setMsg("选中的菜单有角色关联！请先取消角色关联。");
//                ret.setFlag(CodeEnum.ERROR.value());
//                return ret.convertResultJson();
//            }
            sysResourceRepository.deleteResourcesById(asList);

            shiroFilerChainManager.initFilterChains(sysResourceRepository.findAll());
            CacheUtils.remove("findAllOfParent");
            SessionUtils.clearAllCachedAuthorizationInfo();
        } catch (Exception e) {
            e.printStackTrace();
            ret.setMsg("删除失败");
            ret.setFlag(CodeEnum.ERROR.value());
        }
        return ret.convertResultJson();
    }
    @Override
    @Transactional
    public Map<String, Object> saveResource(SysResource sysResource) {
        ResultJsonFormat rj = new ResultJsonFormat(CodeEnum.SUCCESS.value());
        try {
            sysResource.setIconClass(StringEscapeUtils.unescapeHtml4(sysResource.getIconClass()));
            if(StringUtils.isNoneBlank(sysResource.getCode())){
                SysResource dataResource = sysResourceRepository.findByCode(sysResource.getCode());
                if (dataResource!=null && !dataResource.getId().equals(sysResource.getId())) {
                    rj.setFlag(CodeEnum.Failed.value());
                    rj.setMsg("CODE已存在");
                    return rj.convertResultJson();
                }
            }
            sysResource.setIsButton(sysResource.getIsButton()==null?0:sysResource.getIsButton());
            if(StringUtils.isBlank(sysResource.getParentResource().getId())){
                sysResource.setParentResource(null);
            }
            if(StringUtils.isBlank(sysResource.getUrl())){
                sysResource.setUrl("N/A");
            }

            if(StringUtils.isBlank(sysResource.getId())){
                sysResource.preInsert();
                super.save(sysResource);
            }else{
                SysResource dbbean = sysResourceRepository.findOne(sysResource.getId());
                dbbean.EntityCopy(dbbean,sysResource);
                dbbean.preUpdate();

                if(sysResource.getParentResource()!=null){
                    dbbean.setParentResource(sysResourceRepository.findOne(sysResource.getParentResource().getId()));
                }

            }
            shiroFilerChainManager.initFilterChains(sysResourceRepository.findAll());
            SessionUtils.clearAllCachedAuthorizationInfo();
            CacheUtils.remove("findAllOfParent");
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
        return rj.convertResultJson();
    }
    @Override
    public List<TreeNodeVo> findMenuTree(String keyCode){
        Subject subject = SessionUtils.getSubject();
        SysResource res = sysResourceRepository.findByCode(keyCode);
        return this.findSonMenuTree(res,subject);
    }
    public List<TreeNodeVo> findSonMenuTree(SysResource resoure,Subject subject){
        List<TreeNodeVo> treeNodeLi = new ArrayList<TreeNodeVo>();
        for(SysResource sonResoure:resoure.getChildrenResource()){
            if(subject!=null && subject.isPermitted(sonResoure.getCode())){
                TreeNodeVo vo = new TreeNodeVo();
                vo.setId(sonResoure.getId());
                vo.setUrl(sonResoure.getUrl());
                vo.setLeaf(sonResoure.getIsButton()==0);
                vo.setIconCls(sonResoure.getIconClass());
                vo.setIconSkin(sonResoure.getIconClass());
                vo.setName(sonResoure.getName());
                vo.setText(sonResoure.getName());
                if(sonResoure.getChildrenResource()!=null && !sonResoure.getChildrenResource().isEmpty()){
                    vo.setChildren(findSonMenuTree(sonResoure, subject));
                }
                treeNodeLi.add(vo);
            }
        }
        return treeNodeLi;
    }
    @Override
    public void initSaveList(List<SysResource> list) {
        List<SysResource> perLi = new ArrayList<SysResource>();
        List<String> perLiId = new ArrayList<String>();
        List<SysResource> perLi2 = new ArrayList<SysResource>();
        List<String> perLiId2 = new ArrayList<String>();
        //资源id不能自动生成  所有此处用jdbc
        String sql ="insert into sys_resource (CODE, ICON_CLASS, IS_BUTTON, NAME, P_ID, CREATE_DATE, REMARK, URL, ID) values (?, ?, ?, ?, ?, ?, ?, ?, ?)";
        for(SysResource resource : list){
            if(resource.getParentResource()==null){
                //父级id为空
                jdbcTemplate.update(sql,  new Object[] {resource.getCode(),resource.getIconClass(),resource.getIsButton(),resource.getName(),null,resource.getCreateDate(),resource.getRemark(),resource.getUrl(),resource.getId()});
                perLi.add(resource);
                perLiId.add(resource.getId());
            }
        }
        list.removeAll(perLi);
        if(list.isEmpty()){
            return;
        }
        for(SysResource resource : list){
            if(perLiId.contains(resource.getParentResource().getId())){
                //父级id不为空
                jdbcTemplate.update(sql,  new Object[] {resource.getCode(),resource.getIconClass(),resource.getIsButton(),resource.getName(),resource.getParentResource().getId(),resource.getCreateDate(),resource.getRemark(),resource.getUrl(),resource.getId()});
                perLi2.add(resource);
                perLiId2.add(resource.getId());
            }
        }
        list.removeAll(perLi2);
        if(list.isEmpty()){
            return;
        }
        initSaveList(list, perLi2, perLiId2, sql);
    }

    public void  initSaveList(List<SysResource> list,List<SysResource> perLi,List<String> perLiId,String sql){
        for(SysResource resource : list){
            if(perLiId.contains(resource.getParentResource().getId())){
                jdbcTemplate.update(sql,  new Object[] {resource.getCode(),resource.getIconClass(),resource.getIsButton(),resource.getName(),resource.getParentResource().getId(),resource.getCreateDate(),resource.getRemark(),resource.getUrl(),resource.getId()});
                perLi.add(resource);
                perLiId.add(resource.getId());
            }
        }
        list.removeAll(perLi);
        if(!list.isEmpty()){
            initSaveList(list, perLi, perLiId,sql);
        }
    }
}
